// 项目专属的工具封装
/**
 * @export msg(message, type) 提示消息
 * @export loading(show) 全屏价值提示
 * @export (message, title, callback, type) 弹窗提示
 * @export confirm(message, title, ok, fail, type) 确认操作弹窗
 * @export notification(message, title, onclick, type) 通知消息
 * @export href_handle(href, timeout) 统一的链接处理函数，可以设定倒计时，倒计时之前再次调用无效
 *
 * @export function
 */


import {ElLoading, ElMessage, ElMessageBox, ElNotification} from "element-plus";
import i18n from "@/vue_plugin/i18n/index.js";
import router from "@/vue_plugin/router_auto.js";
import {_config, decode_config, in_right, json_decode_object} from "@/js/s94_tool.js";
import main from "@/main.js";
import s94Mjs from "s94-js";
import {use_this_admin} from "@/store/this_admin.js";

// --------------------------- 消息方法，每个项目几乎必须 ----------------------------
function i18n_t(zh){
    // TODO 如果有国际化的需求，此处需要替换为项目的国际化返回方法
    return zh;
}

export function toast(message, type){
    return ElMessage({message, type});
}
toast.info = function (message){
    return toast(message, 'info');
}
toast.warning = function (message){
    return toast(message, 'warning');
}
toast.ok = toast.success = function (message){
    return toast(message, 'success');
}
toast.fail = toast.error = function (message){
    return toast(message, 'error');
}

export let msg = toast;

export function loading(show){
    if (typeof show === 'undefined') show = !loading.status;
    loading.status = show;
    if (loading.th) return;
    loading.th = setTimeout(()=>{
        loading.th = false;
        if (loading.status && !loading.service_return){
            loading.service_return = ElLoading.service({
                lock: true,
                background: 'rgba(0, 0, 0, 0.7)',
            })
        }
        if (!loading.status && loading.service_return){
            loading.service_return.close();
            loading.service_return = null;
        }
    })
}
loading.show = function (){
    loading(true);
}
loading.hide = function (){
    loading(false);
}

export function alert(message, title, callback, type){
    title = title || i18n_t('提示');
    if (typeof callback === 'function') return alert(message, title).then(callback, ()=>{});
    return new Promise((resolve, reject)=>{
        ElMessageBox.alert(message, title, {
            confirmButtonText: i18n_t('确认'),
            callback: resolve,
            type,
        })
    })
}
alert.ok = alert.success = function (message, title, onclick){
    return alert(message, title, onclick, 'success');
}
alert.fail = alert.error = function (message, title, onclick){
    return alert(message, title, onclick, 'error');
}
alert.warning = function (message, title, onclick){
    return alert(message, title, onclick, 'warning');
}
alert.info = function (message, title, onclick){
    return alert(message, title, onclick, 'info');
}

export function confirm(message, title, type, ok, fail){
    title = title || i18n_t('确认操作');
    if (typeof ok === 'function' || typeof fail === 'function') return confirm(message, title, type).then(ok, fail);
    return ElMessageBox.confirm(message, title, {
        type,
        confirmButtonText: i18n_t('确认'),
        cancelButtonText: i18n_t('取消'),
        dangerouslyUseHTMLString: true,
    });
}
confirm.ok = confirm.success = function (message, title, ok, fail){
    return confirm(message, title, ok, fail, 'success');
}
confirm.fail = confirm.error = function (message, title, ok, fail){
    return confirm(message, title, ok, fail, 'error');
}
confirm.warning = function (message, title, ok, fail){
    return confirm(message, title, ok, fail, 'warning');
}
confirm.info = function (message, title, ok, fail){
    return confirm(message, title, ok, fail, 'info');
}

export function notification(message, title, onclick, type){
    if (typeof onclick === 'function') return notification.success(message).then(onclick, ()=>{});
    title = title || i18n_t('通知');
    return new Promise((onClick, reject)=>{
        ElNotification({type, message, title, onClick, dangerouslyUseHTMLString: true});
    })
}
notification.ok = notification.success = function (message, title, onclick){
    return notification(message, title, onclick, 'success');
}
notification.fail = notification.error = function (message, title, onclick){
    return notification(message, title, onclick, 'error');
}
notification.warning = function (message, title, onclick){
    return notification(message, title, onclick, 'warning');
}
notification.info = function (message, title, onclick){
    return notification(message, title, onclick, 'info');
}

// ------------------------------- 消息类方法end ---------------------------------

export function getModelMap(){
    return _config('model_map');
}


/**统一的链接处理函数，可以设定倒计时，倒计时之前再次调用无效
 * @param {String|Number} href 链接地址，可以用特殊数值表示特殊地址，例如：上一页(-1)
 * @param {Number} [timeout] 倒计时，毫秒
 */
export function href_handle(href, timeout){
    if (!href || href_handle.runing) return;
    function run(){
        href_handle.runing = false;
        // 特殊 href 处理
        if (href === -1) {
            return router.back();
        }
        let in_router = false;
        // 判断是否为url链接
        if (href.indexOf('http')!==0 && href.indexOf('//')!==0){
            let i = href.indexOf('?');
            let path = i===-1 ? href : href.substring(0, i);
            let base = router.options.history.base;
            if (base && path.indexOf(base)===0) {
                path = path.substring(base.length);
                in_router = router.has_path(path);
                if (in_router) href = href.substring(base.length);
            }else {
                in_router = router.has_path(path);
            }
        }
        if (in_router){
            router.push(href);
        }else {
            window.location.href = href;
        }
    }
    if (timeout>0){
        href_handle.runing = true;
        setTimeout(run, timeout)
    }else {
        run();
    }
}
/**报错后回退
 * @param {string} message 提示消息，可以为空
 * @param {Number} [timeout] 延时执行，默认：1500
 * @param {string} [href] 跳转地址，规则参考href_handle，默认：-1
 */
export function error_back(message, timeout, href){
    if(message) msg.error(message);
    href = href || -1;
    href_handle(href, timeout || 1500);
}

/**判断管理员是否拥有指定权限
 * @param {string} right
 * @param {Array} [rights] 权限集，默认取管理员当前的权限集
 * @returns {boolean|boolean}
 */
export function in_right_admin(right, rights){
    console.debug('in_right_admin() -> use_this_admin().in_right()')
    return use_this_admin().in_right(right);
    if (!rights){
        rights = use_this_admin().rights || [];
    }
    return in_right(right, rights);
}

/**字段参数类型，
 * @param {number} [can] 可以的配置，使用&运算判断
 * @param {String} [col] 指定返回的列，label、component
 * @returns {{}}
 */
export function field_type(can, col){
    let map = {}, res = {};
    if (typeof(can) === 'undefined'){
        map = field_type.map;
    }else {
        Object.keys(field_type.map).forEach(k=>{
            let row = field_type.map[k];
            if (can & row.can) map[k] = row;
        })
    }
    if (~['label','component'].indexOf(col)){
        Object.keys(map).forEach(k=>{
            let row = map[k];
            res[k] = row[col];
        })
    }else {
        res = map;
    }
    return res;
}
field_type.CAN_CONFIG = 1; // 系统配置可用
field_type.CAN_PARAM = 2; // 自定义参数可用
field_type.CAN_MODEL_FIELD = 4; // 模型字段可用
field_type.CAN_MODEL_FIELD_WHERE = 8; // 模型筛选表达字段可用
field_type.map = {
    text_one:           {can:0b1111, label:'单行文本'},
    text_one_code:      {can:0b1111, label:'单行文本-代码补齐'},
    text_more:          {can:0b0111, label:'多行文本'},
    text_between:       {can:0b1111, label:'文本区间'},
    editor:             {can:0b0101, label:'编辑器'},
    editor_wechat:      {can:0b0000, label:'编辑器(微信)'},
    checkbox:           {can:0b1101, label:'多选'},
    custom_object:      {can:0b0101, label:'自定义对象'},
    date:               {can:0b1101, label:'日期'},
    date_between:       {can:0b1101, label:'日期(区间)'},
    datetime:           {can:0b1101, label:'时间戳'},
    datetime_between:   {can:0b1101, label:'时间戳(区间)'},
    select_one:         {can:0b1111, label:'下拉单选'},
    select_more:        {can:0b1101, label:'下拉多选'},
    radio:              {can:0b1111, label:'单选'},
    radio_switch:       {can:0b0101, label:'开关'},
    radio_switch_group: {can:0b0001, label:'开关组'},
    position:           {can:0b0100, label:'位置'},
    duration:           {can:0b1101, label:'时长'},
    log_list:           {can:0b0100, label:'日志'},
    link_info:          {can:0b0100, label:'链接详情'},
    json_param:         {can:0b0101, label:'自定义参数'},
    json_param_arr:     {can:0b0101, label:'自定义参数集'},
    json_param_checkbox:{can:0b0101, label:'自选参数'},
    list_id:            {can:0b1101, label:'ID单选'},
    list_ids:           {can:0b1101, label:'ID多选'},
    list:               {can:0b0100, label:'列表'},
    file:               {can:0b0111, label:'素材文件'},
    file_img:           {can:0b0101, label:'图片'},
    file_imgs:          {can:0b0111, label:'多图'},
    form_list:          {can:0b0101, label:'表单数据列表'},
    wechat_file:        {can:0b0001, label:'微信素材'},
    wechat_cert:        {can:0b0001, label:'微信证书'},
    iconfont:           {can:0b0101, label:'字体图标'},
    area_4l:            {can:0b0100, label:'选择区域'},
    validate_rule:      {can:0b0000, label:'验证规则'},
    select_address:     {can:0b0100, label:'地址选择'},
    sku:                {can:0b0100, label:'规格配置'},
    additional:         {can:0b0100, label:'加购项配置'},

    hidden:             {can:0b1100, label:'隐藏'},
}
/**返回指定类型的组件config参数配置
 * @param {string} type 类型名称
 * @returns {{remove: boolean}}
 */
field_type.component_config = function (type){
    let res = {remove:false};
    if (/date/.test(type)){
        res.label = '时间格式';
        res.tips = "例如：Y-M-D H:I:S";
    }else if (/^(radio|checkbox|select)/.test(type)){
        res.label = '选项配置';
        res.tips = "格式：选项文本|选项值，多个逗号分隔";
    }else if (/^file/.test(type)){
        res.label = '文件类型';
        res.tips = "指定文件后缀名，多个逗号分隔，为空表示不限制";
    }else if (/^list_ids?/.test(type)){
        res.label = '列表页地址';
        res.tips = "ID选择的列表页面地址";
    }else if ('text_one'===type) {
        res.label = '类型';
        res.tips = '输入元素类型，password：密码,number：数值,color：颜色,range：范围。默认为普通文本(text)。range的范围固定为0-100';
    }else if ('json_param'===type || 'json_param_arr'===type) {
        res.label = '参数配置';
        res.tips = 'json格式，例如[{"name":"img","label":"图片","type":"file_img"},{"name":"text","label":"文本","type":"text_one"}]';
    }else if ('json_param_checkbox'===type) {
        res.label = '参数配置';
        res.tips = 'json格式，包含key_options、input，例如{"key_options":"姓名|name,电话|phone","input":{"type":"text_one"}}';
    }else if ('duration'===type) {
        res.label = '特殊时长';
        res.tips = '用来指定特殊的时长值，格式：介绍|时长值，多个逗号分隔。例如：永久|0，表示设为0时，显示永久，而不是0秒';
    }else if ('log_list'===type) {
        res.label = '参数需求';
        res.tips = '多个逗号分隔，可选值：time、status、files';
    }else {
        return {remove:true};
    }
    return res;
}


export function bind_param(row){
    let res = {};
    for (const k in row) {
        if (!~['name','label','value','tips','type','onchange','inline'].indexOf(k)) res[k] = row[k];
    }
    return res;
}

/**根据表名，获取对应的列表配置
 * @param {string} path 列表页面路径
 * @returns {[{name: string, width: string, label: string, type: string},{name: string, label: string}]|*}
 */
export function list_cols(path){
    path = path.replace(/^\//,'');
    switch (path){
        case 'admin/index': return [
            {name:'head_img', label:'头像', width:'60px', type:'file_img'},
            {name:'name', label:'用户名', width: '120px'},
            {name:'phone', label:'电话号码', width:'120px'},
            {name:'nickname', label:'昵称'},
            {name:'truename', label:'真实姓名', width: '120px'},
        ];
        case 'admin_role/index': return [
            {name:'name', label:'角色名'},
        ];
        case 'agent/index': return [
            {name:'head_img', label:'头图', width:'60px', type:'file_img'},
            {name:'title', label:'标题'},
            {name:'phone', label:'用户电话', width:'120px'},
            {name:'nickname', label:'用户昵称', width:'120px'},
        ];
        case 'category/index': return [
            {name:'model_name', label:'模型', type:'select_one', config:decode_config(_config('model_map'), {content_key:'label', value_key:'name'}), width:'100px'},
            {name:'head_img', label:'缩略图', width:'80px', type:'file_img'},
            {name:'name', label:'类目名', align:'left'},
            {name:'is_show', label:'是否显示', type:'radio_switch', config:['否','是'], width: '80px'},
        ];
        case 'kickback_type/index': return [
            {name:'title', label:'佣金名称'},
            {name:'type', label:'类型', type:'select_one', config:['订单佣金','邀新佣金','邀请下单佣金'], width:'120px'},
        ];
        case 'message_template/index': return [
            {name:'title', label:'标题', width: '200px'},
            {name:'template_code', label:'模板code', min_width:'200px'},
            {name:'type', label:'消息类型', width:'85px',type:'select_one',config:_config('status_alias_map.message_template.type')},
            {name:'content', label:'消息内容', type:'text_more', min_width:'200px'},
        ];
        case 'user/index': return [
            {name:'head_img', label:'头像', width:'60px', type:'file_img'},
            {name:'phone', label:'电话号码', width:'120px'},
            {name:'nickname', label:'昵称'},
            {name:'sex', label:'性别', width:'40px',type:'select_one',config:'未知|0,男|1,女|2'},
        ];
        case 'user_kickback/index': return [
            {name:'head_img', label:'头像', width:'60px', type:'file_img'},
            {name:'phone', label:'电话号码',  width:'120px'},
            {name:'nickname', label:'昵称', width:'120px'},
            {name:'title', label:'佣金标题', width:'150px'},
            {name:'info', label:'明细', min_width:'100px'},
            {name:'money', label:'金额', width:'75px'},
        ];
        case 'user_withdraw/index': return [
            {name:'head_img', label:'头像', width:'60px', type:'file_img'},
            {name:'phone', label:'电话号码',  width:'120px'},
            {name:'nickname', label:'昵称', width:'120px'},
            {name:'money', label:'提现金额', width:'75px'},
            {name:'service_money', label:'手续费', width:'75px'},
            {name:'withdraw_money', label:'到账金额', width:'75px'},
            {name:'note_user', label:'用户备注'},
        ];
        case 'wechat_menu/index': return [
            {name:'alias', label:'标题', min_width:'200px', align:'left'},
        ];
        case 'model_v2_form_param/index': return [
            {name:'name', label:'字段名',width:'160px',align:'left'},
            {name:'field', label:'数据库字段', width:'100px'},
            {name:'label', label:'别名', width:'100px'},
            {name:'type', label:'字段类型',type:'select_one',config:field_type(field_type.CAN_MODEL_FIELD, 'label'),width:'100px'},
            {name:'can_edit', label:'可编辑', type:'radio_switch', config:'否|0,是|1', width:'60px'},
            {name:'compute_code', label:'计算值', min_width:'100px'},
            {name:'value', label:'默认值', min_width:'100px'},
            {name:'validate', label:'验证规则', type:'validate_rule', value:'[]', min_width:'150px'},
            {name:'handle_type', label:'处理类型',type:'select_one',config:'无|,JSON|json,规格|sku_config,加购项|additional_config',width:'100px'},
        ];
        case 'model_v2_form_param/index_info': return [
            {name:'name', label:'字段名',width:'160px',align:'left'},
            {name:'field', label:'数据库字段', width:'120px'},
            {name:'label', label:'别名', width:'100px'},
            {name:'type', label:'字段类型',type:'select_one',config:field_type(field_type.CAN_MODEL_FIELD, 'label'),width:'100px'},
            {name:'compute_code', label:'计算值', min_width:'100px'},
        ];
        case 'model_v2_form_param/index_list': return [
            {name:'name', label:'字段名',width:'160px',align:'left'},
            {name:'field', label:'数据库字段', width:'120px'},
            {name:'label', label:'别名', width:'100px'},
            {name:'type', label:'字段类型',type:'select_one',config:field_type(field_type.CAN_MODEL_FIELD, 'label'),width:'100px'},
            {name:'compute_code', label:'计算值', min_width:'100px'},

            {label:'宽度',name:'props_width',width:'100px'},
            {label:'最小宽度',name:'props_min_width',width:'100px'},
            {label:'对齐方式',name:'props_align',width:'100px'},
            {label:'固定位置',name:'props_fixed',type:'radio',config:"不固定|,左边|left,右边|right",width:'100px'},
        ];
        case 'model_v2_where_param/index': return [
            {name:'field', label:'字段名',width:'140px',align:'left'},
            {name:'method', label:'检索类型', width:'100px'},
            {name:'label', label:'别名', width:'100px'},
            {name:'tips', label:'介绍'},
            {name:'type', label:'组件类型',type:'select_one',config:field_type(undefined, 'label'),width:'100px'},
            {name:'value', label:'默认值'},
        ];
        case 'model/index': return [
            {name:'name', label:'模型名',width:'120px'},
            {name:'alias', label:'别名', width:'120px'},
            {name:'link_model', label:'关联模型', min_width:'120px'},
            {name:'link_order', label:'订单系统', type:'radio_switch',  width:'70px'},
            {name:'link_user', label:'用户系统', type:'radio_switch',  width:'70px'},
        ];
        case 'param/index': return [
            {name:'name', label:'参数名', width: '120px'},
            {name:'type', label:'输入类型', width: '120px', type: 'select_one', config: {text_one:'单行文本',text_more:'多行文本',radio:'单选'}},
            {name:'tips', label:'提示信息'},
            {name:'validate', label:'是否必填', type:'radio_switch', config:{'["nullable"]':'否','["required"]':'是'}, width: '120px'},
            {name:'value', label:'默认值', width: '120px'},
        ];
        case 'order/index': return [
            {name:'order_pay_order_no', label:'订单号', type:'text_more', width:'100px'},
            {name:'user', label:'下单用户', type:'json_param', config:[{"name":"nickname","label":"昵称"},{"name":"phone","label":"电话"}], width:'140px', align:'left'},
            {name:'head_img', label:'头图', width:'60px', type:'file_img'},
            {name:'title', label:'标题'},
        ];
    }

    return [
        {name:'head_img', label:'头图', width:'60px', type:'file_img'},
        {name:'title', label:'标题'},
    ];
}

export function list_handle(path, list){
    path = path.replace(/^\//,'');
    switch (path) {
        case 'model_v2_form_param/index_list':{
            list.forEach(row=>{
                let config = json_decode_object(row.list_props);
                row.props_width = config.width || '';
                row.props_min_width = config.min_width || '';
                row.props_align = config.align || '';
                row.props_fixed = config.fixed || '';
            })
        }break;
    }
    return list;
}

export function selectList(path, more){
    return new Promise((resolve, reject) => {
        iframe({
            href: path,
            btns: {
                '确定_primary'(win_app){
                    let selected = typeof win_app.get_selected === 'function' ? win_app.get_selected() : (win_app.$refs?.list_url?.selected || []);
                    if (!more && selected.length != 1) return msg.fail('只能选择一个');
                    resolve(selected);
                    win_app.__iframe.show = false;
                }
            }
        })
    })
}


/**隐藏子窗口，show=false
 * @param {string} href 窗口地址
 */
iframe.hide = function (href){
    return main.$refs.iframe_list.hide(href);
}

/**子窗口列表
 * @param {Object|string} config 配置，如果为字符串，表示href
 * @param {Array|string|object} config.href 窗口地址
 * @param {Array|object} [config.btns] 按钮列表
 * @param {string} [config.width] 窗口宽度，默认为80%
 * @returns {*} 组件实例对象
 */
export function iframe(config){
    return main.$refs.iframe_list.show(config);
}
/**移除子窗口，窗口从列表中删除
 @param {string} href 窗口地址
 */
iframe.remove = function (href){
    return main.$refs.iframe_list.remove(href);
}
/**子窗口执行方法
 * @param {string} href 窗口地址
 * @param {string} function_name 方法名，多级用.分割，例如：this.$refs.forms.init
 * @param {*} args 方法执行传入的参数，可以传入多个
 * @returns {*}
 */
iframe.exe = function (href, function_name, ...args){
    return main.$refs.iframe_list.exe(href, function_name, ...args);
}

/**显示文件预览
 * @param {string} src 文件地址
 * @returns {*} 组件实例对象
 */
export function show_file(src){
    return main.$refs.show_file.hide(src);
}